package com.zbkj.service.dividend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.user.User;
import com.zbkj.service.dividend.model.DividendPoolConfig;
import com.zbkj.service.dividend.model.DividendPoolRecord;
import com.zbkj.service.dividend.service.DividendPoolConfigService;
import com.zbkj.service.dividend.service.DividendPoolRecordService;
import com.zbkj.service.dividend.service.DividendPoolService;
import com.zbkj.service.service.SystemConfigService;
import com.zbkj.service.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户分红服务实现类
 */
@Slf4j
@Service
public class DividendPoolServiceImpl implements DividendPoolService {

    @Autowired
    private DividendPoolConfigService dividendPoolConfigService;

    @Autowired
    private UserService userService;

    @Resource
    private DividendPoolRecordService dividendPoolRecordService;

    @Autowired
    private SystemConfigService systemConfigService;

    // 分红总额比例配置键
    private static final String TOTAL_PROFIT_RATIO_KEY = "total_pool_ratio";

    /**
     * 订单支付时执行分红
     */
    @Override
    @Transactional
    public boolean executeOrderDividend(Order order) {
        if (order == null || order.getPayPrice() == null) {
            log.error("订单信息为空或订单金额为空");
            return false;
        }

        String orderNo = order.getOrderNo();
        log.info("开始执行订单分红，订单号: {}, 订单金额: {}", orderNo, order.getPayPrice());

        try {
            BigDecimal orderAmount = order.getPayPrice();

            // 1. 计算分红金额分配
            Map<String, Object> dividendResult = calculateOrderDividend(orderAmount);
            if (dividendResult == null || !(boolean) dividendResult.get("success")) {
                log.error("计算分红金额失败，订单号: {}", orderNo);
                return false;
            }

            // 2. 获取用户分红映射
            @SuppressWarnings("unchecked")
            Map<Integer, BigDecimal> userDividendMap = (Map<Integer, BigDecimal>) dividendResult.get("userDividendMap");
            if (CollectionUtils.isEmpty(userDividendMap)) {
                log.warn("没有用户参与分红，订单号: {}", orderNo);
                return true; // 没有用户参与分红也算成功
            }

            // 3. 执行分红分发
            boolean distributeSuccess = distributeDividendToUsers(orderAmount, userDividendMap);

            if (distributeSuccess) {
                // 4. 记录分红记录
                boolean recordSuccess = recordDividendDetails(order, userDividendMap, dividendResult);
                if (recordSuccess) {
                    log.info("订单分红执行成功，订单号: {}, 分红总金额: {}, 参与用户数: {}",
                            orderNo, orderAmount, userDividendMap.size());
                } else {
                    log.error("记录分红详情失败，订单号: {}", orderNo);
                    // 记录失败不影响分红分发成功
                }
            }

            return distributeSuccess;

        } catch (Exception e) {
            log.error("执行订单分红异常，订单号: {}", orderNo, e);
            throw new RuntimeException("订单分红执行失败: " + e.getMessage(), e);
        }
    }

    /**
     * 记录分红详情到数据库
     */
    private boolean recordDividendDetails(Order order, Map<Integer, BigDecimal> userDividendMap,
                                          Map<String, Object> dividendResult) {
        try {
            List<DividendPoolRecord> records = new ArrayList<>();

            // 获取分红池用户数量信息
            Map<Integer, Integer> poolUserCount = getPoolUserCount();
            BigDecimal totalPoolRatio = (BigDecimal) dividendResult.get("totalPoolRatio");
            @SuppressWarnings("unchecked")
            Map<Integer, BigDecimal> poolAmountMap = (Map<Integer, BigDecimal>) dividendResult.get("poolAmountMap");

            // 获取各分红池的总金额（用于计算分红池总金额）
            BigDecimal totalPoolAmount = calculateTotalPoolAmount();

            for (Map.Entry<Integer, BigDecimal> entry : userDividendMap.entrySet()) {
                Integer userId = entry.getKey();
                BigDecimal dividendAmount = entry.getValue();

                // 获取用户信息
                User user = userService.getById(userId);
                if (user == null) {
                    log.warn("用户不存在，跳过记录分红，用户ID: {}", userId);
                    continue;
                }

                // 获取用户所在分红池配置
                DividendPoolConfig userConfig = getDividendConfigByDividendId(user.getDividendPoolId());
                if (userConfig == null) {
                    log.warn("用户分红配置不存在，用户ID: {}, dividendId: {}", userId, user.getDividendPoolId());
                    continue;
                }

                // 计算该分红池的用户数量
                Integer userPoolUserCount = poolUserCount.get(userConfig.getId());
                if (userPoolUserCount == null) {
                    userPoolUserCount = 0;
                }

                // 计算该分红池的总金额
                BigDecimal userPoolTotalAmount = poolAmountMap.get(userConfig.getId());
                if (userPoolTotalAmount == null) {
                    userPoolTotalAmount = BigDecimal.ZERO;
                }

                // 创建分红记录
                DividendPoolRecord record = new DividendPoolRecord();
                record.setId(UUID.randomUUID().toString().replace("-", ""));
                record.setUserId(userId);
                record.setOrderNo(order.getOrderNo());
                record.setProfitRatio(userConfig.getProfitRatio());
                record.setDividendAmount(dividendAmount);
                record.setOrderAmount(order.getPayPrice());
                record.setPoolTotalAmount(userPoolTotalAmount);
                record.setPoolUserCount(userPoolUserCount);
                record.setDividendDate(LocalDateTime.now());
                record.setCreateTime(LocalDateTime.now());

                records.add(record);
            }

            // 批量插入分红记录
            if (!CollectionUtils.isEmpty(records)) {
                int result = dividendPoolRecordService.batchCreateDividendRecords(records);
                log.info("分红记录保存成功，订单号: {}, 记录数: {}", order.getOrderNo(), result);
                return result > 0;
            }

            return false;

        } catch (Exception e) {
            log.error("记录分红详情异常，订单号: {}", order.getOrderNo(), e);
            return false;
        }
    }

    /**
     * 计算分红池总金额（模拟方法，实际需要根据业务逻辑实现）
     */
    private BigDecimal calculateTotalPoolAmount() {
        try {
            // 这里可以根据实际业务逻辑计算分红池总金额
            // 例如：所有分红池用户余额总和，或者固定值等
            return BigDecimal.valueOf(1000000); // 模拟值
        } catch (Exception e) {
            log.error("计算分红池总金额异常", e);
            return BigDecimal.ZERO;
        }
    }

    /**
     * 根据dividendId获取分红配置
     */
    private DividendPoolConfig getDividendConfigByDividendId(Integer dividendId) {
        if (dividendId == null || dividendId == 0) {
            return null;
        }

        try {
            return dividendPoolConfigService.getById(dividendId);
        } catch (Exception e) {
            log.error("根据dividendId获取分红配置异常，dividendId: {}", dividendId, e);
            return null;
        }
    }

    /**
     * 查询用户累计分红金额
     */
    @Override
    public BigDecimal getUserTotalDividend(Integer userId) {
        if (userId == null) {
            return BigDecimal.ZERO;
        }

        try {
            BigDecimal totalDividend = dividendPoolRecordService.getTotalDividendByUserId(userId);
            log.debug("查询用户累计分红金额，用户ID: {}, 累计金额: {}", userId, totalDividend);
            return totalDividend != null ? totalDividend : BigDecimal.ZERO;
        } catch (Exception e) {
            log.error("查询用户累计分红金额异常，用户ID: {}", userId, e);
            return BigDecimal.ZERO;
        }
    }

    /**
     * 计算订单分红金额
     */
    @Override
    public Map<String, Object> calculateOrderDividend(BigDecimal orderAmount) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 获取所有启用的分红配置
            List<DividendPoolConfig> configList = dividendPoolConfigService.getAllActiveConfigs();
            if (CollectionUtils.isEmpty(configList)) {
                log.warn("没有启用的分红配置");
                result.put("success", false);
                result.put("message", "没有启用的分红配置");
                return result;
            }

            // 2. 获取各分红池用户数量
            Map<Integer, Integer> poolUserCount = getPoolUserCount();
            if (CollectionUtils.isEmpty(poolUserCount)) {
                log.warn("分红池中没有用户");
                result.put("success", false);
                result.put("message", "分红池中没有用户");
                return result;
            }

            // 3. 获取分红总额比例（从系统配置获取，默认50%）
            BigDecimal totalPoolRatio = getTotalProfitRatio();

            // 4. 计算各分红池应分金额
            Map<Integer, BigDecimal> poolAmountMap = new HashMap<>();
            BigDecimal totalDistributed = BigDecimal.ZERO;

            for (DividendPoolConfig config : configList) {
                Integer configId = config.getId();
                Integer userCount = poolUserCount.get(configId);

                if (userCount != null && userCount > 0) {
                    // 该分红池应分金额 = 订单金额 × 分红总额比例 × 分红比例
                    BigDecimal poolAmount = orderAmount.multiply(totalPoolRatio)
                            .multiply(config.getProfitRatio())
                            .setScale(2, RoundingMode.HALF_UP);

                    poolAmountMap.put(configId, poolAmount);
                    totalDistributed = totalDistributed.add(poolAmount);
                }
            }

            // 5. 计算每个用户应分金额
            Map<Integer, BigDecimal> userDividendMap = new HashMap<>();

            for (DividendPoolConfig config : configList) {
                Integer configId = config.getId();
                BigDecimal poolAmount = poolAmountMap.get(configId);

                if (poolAmount != null && poolAmount.compareTo(BigDecimal.ZERO) > 0) {
                    // 获取该分红池的所有用户
                    List<User> poolUsers = getPoolUser(config.getId());
                    if (!CollectionUtils.isEmpty(poolUsers)) {
                        // 平均分配给该分红池的用户
                        BigDecimal userAmount = poolAmount.divide(
                                BigDecimal.valueOf(poolUsers.size()), 2, RoundingMode.HALF_UP);

                        for (User poolUser : poolUsers) {
                            if (Boolean.TRUE.equals(poolUser.getStatus())) { // 只给正常状态的用户分红
                                userDividendMap.put(poolUser.getId(), userAmount);
                            }
                        }
                    }
                }
            }

            result.put("success", true);
            result.put("orderAmount", orderAmount);
            result.put("totalDistributed", totalDistributed);
            result.put("poolAmountMap", poolAmountMap);
            result.put("userDividendMap", userDividendMap);
            result.put("userCount", userDividendMap.size());
            result.put("totalPoolRatio", totalPoolRatio);

            log.info("分红计算完成，订单金额: {}, 分红总金额: {}, 参与用户数: {}, 分红总额比例: {}",
                    orderAmount, totalDistributed, userDividendMap.size(), totalPoolRatio);

        } catch (Exception e) {
            log.error("计算分红金额异常", e);
            result.put("success", false);
            result.put("message", "计算分红金额异常: " + e.getMessage());
        }

        return result;
    }

    /**
     * 获取分红总额比例
     */
    private BigDecimal getTotalProfitRatio() {
        try {
            // 从系统配置获取分红总额比例，默认5%
            String ratioStr = systemConfigService.getValueByKey(TOTAL_PROFIT_RATIO_KEY);
            if (ratioStr != null && !ratioStr.trim().isEmpty()) {
                double ratio = Double.parseDouble(ratioStr);
                return BigDecimal.valueOf(ratio);
            }
        } catch (Exception e) {
            log.warn("获取分红总额比例配置失败，使用默认值5%", e);
        }
        // 默认50%的分红比例
        return new BigDecimal("0.05");
    }

    /**
     * 执行分红到用户佣金字段
     */
    @Override
    @Transactional
    public boolean distributeDividendToUsers(BigDecimal totalAmount, Map<Integer, BigDecimal> userDividendMap) {
        if (CollectionUtils.isEmpty(userDividendMap)) {
            return true;
        }

        try {
            int successCount = 0;
            int totalCount = userDividendMap.size();

            for (Map.Entry<Integer, BigDecimal> entry : userDividendMap.entrySet()) {
                Integer userId = entry.getKey();
                BigDecimal dividendAmount = entry.getValue();

                try {
                    // 更新用户佣金字段
                    boolean updateSuccess = updateUserBrokerage(userId, dividendAmount);
                    if (updateSuccess) {
                        successCount++;
                        log.debug("用户分红成功，用户ID: {}, 分红金额: {}", userId, dividendAmount);
                    } else {
                        log.error("用户分红失败，用户ID: {}, 分红金额: {}", userId, dividendAmount);
                    }
                } catch (Exception e) {
                    log.error("更新用户佣金异常，用户ID: {}", userId, e);
                }
            }

            boolean success = successCount == totalCount;
            if (!success) {
                log.warn("分红分发部分成功，成功数: {}, 总数: {}", successCount, totalCount);
            }

            return success;

        } catch (Exception e) {
            log.error("分发分红到用户异常", e);
            throw new RuntimeException("分红分发失败: " + e.getMessage(), e);
        }
    }

    /**
     * 更新用户佣金字段
     */
    private boolean updateUserBrokerage(Integer userId, BigDecimal dividendAmount) {
        try {
            // 获取用户当前信息
            User user = userService.getById(userId);
            if (user == null) {
                log.error("用户不存在，用户ID: {}", userId);
                return false;
            }

            // 计算新的佣金金额
            BigDecimal currentBrokerage = user.getBrokeragePrice() != null ?
                    user.getBrokeragePrice() : BigDecimal.ZERO;
            BigDecimal newBrokerage = currentBrokerage.add(dividendAmount);

            // 更新用户佣金
            User updateUser = new User();
            updateUser.setId(userId);
            updateUser.setBrokeragePrice(newBrokerage);
            updateUser.setUpdateTime(new Date());


            boolean updateSuccess = userService.updateById(updateUser);

            if (updateSuccess) {
                log.debug("用户佣金更新成功，用户ID: {}, 旧金额: {}, 新金额: {}, 变动金额: {}",
                        userId, currentBrokerage, newBrokerage, dividendAmount);
            }

            return updateSuccess;

        } catch (Exception e) {
            log.error("更新用户佣金异常，用户ID: {}", userId, e);
            return false;
        }
    }

    /**
     * 获取各分红池用户数量
     */
    @Override
    public Map<Integer, Integer> getPoolUserCount() {
        try {
            List<DividendPoolConfig> configList = dividendPoolConfigService.getAllActiveConfigs();
            if (CollectionUtils.isEmpty(configList)) {
                return new HashMap<>();
            }

            Map<Integer, Integer> poolUserCount = new HashMap<>();

            for (DividendPoolConfig config : configList) {
                // 查询该分红池的正常用户数量
                LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(User::getDividendPoolId, config.getId())
                        .eq(User::getStatus, true);
                int userCount = userService.count(queryWrapper);
                poolUserCount.put(config.getId(), userCount);
            }

            return poolUserCount;

        } catch (Exception e) {
            log.error("获取分红池用户数量异常", e);
            return new HashMap<>();
        }
    }

    /**
     * 获取分红池用户列表
     */
    private List<User> getPoolUser(Integer configId){
        try {
            // 获取该分红池的用户列表
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getDividendPoolId, configId)
                    .eq(User::getStatus, true);
            return userService.list(queryWrapper);
        } catch (Exception e) {
            log.error("获取分红池用户列表异常，configId: {}", configId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取分红池配置及用户信息
     */
    @Override
    public List<Map<String, Object>> getPoolConfigWithUsers() {
        try {
            List<DividendPoolConfig> configList = dividendPoolConfigService.getAllActiveConfigs();
            if (CollectionUtils.isEmpty(configList)) {
                return new ArrayList<>();
            }

            return configList.stream().map(config -> {
                Map<String, Object> poolInfo = new HashMap<>();
                poolInfo.put("config", config);
                List<User> users = getPoolUser(config.getId());
                poolInfo.put("users", users);
                poolInfo.put("userCount", users != null ? users.size() : 0);

                return poolInfo;
            }).collect(Collectors.toList());

        } catch (Exception e) {
            log.error("获取分红池配置及用户信息异常", e);
            return new ArrayList<>();
        }
    }

    /**
     * 批量执行分红
     */
    @Override
    @Transactional
    public boolean batchExecuteDividend(List<Order> orders) {
        if (CollectionUtils.isEmpty(orders)) {
            return true;
        }

        try {
            int successCount = 0;

            for (Order order : orders) {
                boolean success = executeOrderDividend(order);
                if (success) {
                    successCount++;
                }
            }

            boolean overallSuccess = successCount == orders.size();
            log.info("批量执行分红完成，成功数: {}, 总数: {}", successCount, orders.size());

            return overallSuccess;

        } catch (Exception e) {
            log.error("批量执行分红异常", e);
            throw new RuntimeException("批量分红执行失败: " + e.getMessage(), e);
        }
    }
}